﻿#if NETSTANDARD2_0 
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
#endif

#if NET35
using Kernelx.Common.DependencyInjection;
#endif


using System;
using System.Collections.Generic;
using System.Linq;
 

namespace Kernelx.Contexts.Configuration
{
    using Kernelx.Contexts.ClientImpls;
    using Core;

    public partial class ClientWorkloadContextOptions : WorkloadContextOptions
    {
        private ClientWorkloadContextOptions(IServiceCollection services)
            => Services = services ?? throw new ArgumentNullException(nameof(services));

        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        public override IServiceCollection Services { get; protected set; }



        private readonly IRequestParameterCollection _defaultRequestParameters = RequsetParameter.Create(new { });
        private readonly IDictionary<Type, object> _serviceObjs = new Dictionary<Type, object>();
        //todo:待完善,服务生命周期未实现,泛型服务类型未实现
        private object GetService(Type serviceType)
        {
            object createTypeInstance(Type type)
            {
                if (type.IsClass)
                {
                    var constructor = type.GetConstructors().FirstOrDefault();
                    if (constructor != null)
                    {
                        var ps = constructor.GetParameters().Select(x => GetService(x.ParameterType)).ToArray();
                        return constructor.Invoke(ps);
                    }
                }
                return null;
            }

            if (_serviceObjs.ContainsKey(serviceType))
                return _serviceObjs[serviceType];
            else
            {
                lock (_serviceObjs)
                {
                    var service = Services.FirstOrDefault(x => x.ServiceType == serviceType);
                    object obj = null;
                    if (service != null)
                    {
                        obj = service.ImplementationFactory?.Invoke(WorkloadStartupContext.Current) ?? service.ImplementationInstance;
                        if (obj == null)
                        {
                            if (service.ServiceType != service.ImplementationType && service.ImplementationType != null)
                                obj = GetService(service.ImplementationType);
                            else
                                obj = createTypeInstance(service.ServiceType);
                        }
                        _serviceObjs.Add(service.ServiceType, obj);
                    }
                    return obj ?? createTypeInstance(serviceType);
                }
            }
        }

        protected override IWorkloadStartupContext Generate() => new ClientWorkloadContext(GetService, _defaultRequestParameters);
    }

}
